//Copyright (C) 2009 Ron Coleman. Contact: ronncoleman@gmail.com
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 3 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


package org.workplicity.android.cia.application;

import java.util.ArrayList;
import java.util.HashSet;

import org.workplicity.android.cia.util.AndroidHelper;
import org.workplicity.elog.entry.Audit;
import org.workplicity.elog.entry.Elog;
import org.workplicity.elog.entry.ElogUser;
import org.workplicity.elog.entry.ElogUser.Function;
import org.workplicity.task.NetTask;
import org.workplicity.worklet.WorkletContext;

import android.app.Application;

/**
 * @author Brian Gormanly
 * @version 1.0
 * 
 * <p>Android Application layer.</p>
 * 
 * <p>This is the singleton layer that will hold the "up to date" client view of
 * the data from the server.  It does not update it's view of the data from
 * the server, instead the other layers of the application update it, and then
 * call the refresh() methods on the View / Activity layer to call upon this
 * information in the presentation.</p>
 */

public class ELogApplication extends Application {


	/**
	 *  Worklet context used by original helper and CIAHelper
	 */
	WorkletContext context;
	
	/**
	 *  ArrayList of all users available
	 */
	ArrayList<ElogUser> allUsers = null;
	
	/**
	 * 	ArrayList of all worklogs available
	 */
	private ArrayList<Elog> allElogs = new ArrayList<Elog>( );
	
	/**
	 * currently selected elog
	 */
	private Elog currentElog;
	
	/**
	 * Boolean that represents whether the current elog is dirty
	 * (has been altered)
	 */
	private Boolean currentElogDirty;
	
	/**
	 * Boolean that represents whether the elogActivity is in
	 * edit or create mode
	 */
	private Boolean createMode = false;
	
	/**
	 *  logged in user
	 */
	ElogUser loggedInUser = null;
	
	private Boolean loginStatus = false;
	
	/**
	 * Helper
	 */
	private AndroidHelper myHelper;
	
	/**
	 * Handles startup tasks related to the application layer.
	 */
	@Override
	public void onCreate() {
		super.onCreate();
	
		// initialize the context
		this.context = WorkletContext.getInstance();
		
		// get the connection info in order
		NetTask.setUrlBase("http://www.valleytg.com/netprevayle/task");
        NetTask.setStoreName("nl");
		
		
		// initialize the current elog to be null
		currentElog = null;
		
	}

	/**
	 * get All Elogs (in the application scope)
	 * @return allElogs
	 */
	public ArrayList<Elog> getAllElogs() {
		return allElogs;
	}

	/**
	 * Set All Elogs for the application scope.  Can be a filtered view
	 * of all the elogs in the server database
	 * @param ArrayList of Elog
	 */
	public void setAllElogs(ArrayList<Elog> allElogs) {
		this.allElogs = allElogs;
	}	
	
	/**
	 * <p>Get the singleton context for the worker</p>
	 * <p>Needed for interaction with the Helper classes</p>
	 * @return context
	 */
	public WorkletContext getContext() {
		return context;
	}

	/**
	 * Set the worklet context
	 * @param context
	 */
	public void setContext(WorkletContext context) {
		this.context = context;
	}
	
	/**
	 * <p>Update Audit</p>
	 * 
	 */
	public void updateAudit(String message) {
        // Build the audit
        Audit audit = new Audit();

        audit.setUserId(this.getLoggedInUser().getId());

        audit.setText(message);

        // Add audit to the front of the list --
        // this obviates need for sorting.
        this.getCurrentElog().getAuditTrail().add(0,audit);

    }

	/**
	 * <p>Gets all the users from the application layer</p>
	 * <p>All users from the application layer may be a different set then
	 * all the users in the server database.  This is controlled by the 
	 * query criteria at the time that the users are added to the application
	 * layer.</p>
	 * @return ArrayList of ElogUsers
	 */
	public ArrayList<ElogUser> getAllUsers() {
		return allUsers;
	}
	
	/**
	 * <p>Gets a single user by the user id</p>
	 * @param id
	 * @return ElogUser
	 */
	public ElogUser getUserById(int id) {

		for(ElogUser user : this.allUsers) {
			if(user.getId() == id) {
				return user;
			}
		}
		
		return null;
		
	}
	
	/**
	 * <p>Gets a single user by the username</p>
	 * @param username
	 * @return ElogUser
	 */
	public ElogUser getUserByUserName(String username) {

		for(ElogUser user : this.allUsers) {
			if(user.getLogname() == username) {
				return user;
			}
		}
		
		return null;
		
	}
	
	/**
	 * <p>Gets full names for all the users in the allUsers ArrayList</p>
	 * @return String array of full (first + last) names
	 */
	public String[] getAllUsersFullNameArray() {
		String[] usersNames = new String[this.allUsers.size()];
		if(this.allUsers != null) {
			for(int i=0; i<this.allUsers.size(); i++) {
				usersNames[i] = this.allUsers.get(i).getFirstName().toString() + " " + this.allUsers.get(i).getLastName().toString();
			}
		}
		
		return usersNames;
	}

	/**
	 * Gets usernames for all the users in the allUsers ArrayList
	 * @return String array of usernames
	 */
	public String[] getAllUsersUsernames() {
		String[] usernames = new String[this.allUsers.size()];
		if(this.allUsers != null) {
			for(int i=0; i<this.allUsers.size(); i++) {
				String temp = this.allUsers.get(i).getLogname().toString();
				usernames[i] = temp;
			}
		}
		
		return usernames;
	}
	
	/**
	 * Gets the descriptions of all the workorders in the allElogs arraylist
	 * @return String array of descriptions
	 */
	public String[] getAllElogsDescriptions() {
		String[] descriptions = new String[this.allElogs.size()];
		if(this.allElogs != null) {
			for(int i=0; i<this.allElogs.size(); i++) {
				String temp = this.allElogs.get(i).getDescription().toString();
				descriptions[i] = temp;
			}
		}
		
		return descriptions;
	}
	
	
	/**
     * This method gathers the subordinates recursively.
     * @param target Target user
     * @param set List compiled so far
     */
    public void gatherSubordinates(ElogUser target,HashSet<ElogUser> set) {
        // If user has no subordinates, then this is the user set
        if (target.getFunction() == Function.WORKER)
            return;

        // Otherwise gather the users that are subordinates of
        // the prime user
        ArrayList<ElogUser> users = this.getAllUsers();

        Integer primeUserId = this.getLoggedInUser().getId();

        for (ElogUser user : users) {
            ElogUser elogUser = user;

            Integer bossId = elogUser.getBossId();
            if (bossId != -1 && bossId.equals(primeUserId)) {
                set.add(elogUser);

                // If this prime user is an exec, then it
                // only supers can point to it...so we'll need
                // to get the supervisor's subordinates
                if (isManagement(target)) {
                    gatherSubordinates(elogUser, set);
                }
            }
        }
    }
	
    /**
     * Returns true if this user is a management type.
     * @param target Target user
     * @return True of the user is in management, false otherwise
     */
    public static boolean isManagement(ElogUser target) {
        Function function = target.getFunction();

        if(function == Function.MANAGER || function == Function.SUPERVISOR ||
                function == Function.DIRECTOR || function == Function.PRESIDENT)
            return true;

        return false;
    }
	
	/**
	 * Set all users for the application scope
	 * @param allUsers
	 */
	public void setAllUsers(ArrayList<ElogUser> allUsers) {
		this.allUsers = allUsers;
	}

	/**
	 * Get the user that is currently logged into the system
	 * @return ElogUser
	 */
	public ElogUser getLoggedInUser() {
		return loggedInUser;
	}

	/**
	 * Set the user that is currently logged into the system
	 * @param ElogUser loggedInUser
	 */
	public void setLoggedInUser(ElogUser loggedInUser) {
		this.loggedInUser = loggedInUser;
	}
	
	/**
	 * Get the current elog
	 * @return Elog currentElog
	 */
	public Elog getCurrentElog() {
		return currentElog;
	}

	/**
	 * Set the current elog
	 * @param Elog currentElog
	 */
	public void setCurrentElog(Elog currentElog) {
		this.currentElog = currentElog;
		
		// set the current elog dirty flag to false
		this.setCurrentElogDirty(false);
	}

	public void setCreateMode(Boolean createMode) {
		this.createMode = createMode;
	}

	public Boolean isCreateMode() {
		return createMode;
	}

	public void setCurrentElogDirty(Boolean currentElogDirty) {
		this.currentElogDirty = currentElogDirty;
	}

	public Boolean getCurrentElogDirty() {
		return currentElogDirty;
	}

	public void setLoginStatus(Boolean loginStatus) {
		this.loginStatus = loginStatus;
	}

	public Boolean getLoginStatus() {
		return loginStatus;
	}

	public void setMyHelper(AndroidHelper myHelper) {
		this.myHelper = myHelper;
	}

	public AndroidHelper getMyHelper() {
		return myHelper;
	}

}


